package com.szw.dlyk.config;

import com.szw.dlyk.config.filter.TokenVerifyFilter;
import com.szw.dlyk.config.handler.MyAccessDeniedHandler;
import com.szw.dlyk.config.handler.MyAuthenticationFailureHandler;
import com.szw.dlyk.config.handler.MyAuthenticationSuccessHandler;
import com.szw.dlyk.config.handler.MyLogoutSuccessHandler;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import static com.szw.dlyk.constant.Constant.LOGIN_URL;

/**
 * @program: dlyk
 * @description: SprpingSecurity配置
 * @author: Songzw
 * @create: 2024-01-21 19:47
 **/


@EnableMethodSecurity //开启方法级别的权限检查
@Configuration
public class securityConfig {

    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

    @Resource
    private TokenVerifyFilter tokenVerifyFilter;

    @Resource
    private MyAccessDeniedHandler myAccessDeniedHandler;


    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,CorsConfigurationSource configurationSource) throws Exception {
        return httpSecurity
                .formLogin((formLogin)->{
                    //登录处理地址 不需要再写Controller
                    formLogin.loginProcessingUrl(LOGIN_URL)
                            .usernameParameter("loginAct")
                            .passwordParameter("loginPwd")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailureHandler);

                })
                .authorizeHttpRequests((authorization)->{
                    authorization.requestMatchers(LOGIN_URL).permitAll()
                    //任何请求都需要登录后才能访问
                            .anyRequest().authenticated();
                })
                //禁用跨站请求伪造
                .csrf( AbstractHttpConfigurer::disable)

                //支持跨域请求
                .cors((cors)->{
                    cors.configurationSource(configurationSource);
                })
                .sessionManagement( (session) -> {
                    //session创建策略
                    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 无session状态，也就是禁用session
                })

                //添加自定义的Filter
                .addFilterBefore(tokenVerifyFilter, LogoutFilter.class)

                //退出
                .logout((logout)->{
                    logout.logoutUrl("/api/logout")
                            .logoutSuccessHandler(myLogoutSuccessHandler);
                })
                //这个是没有权限访问时触发
                .exceptionHandling((exceptionHandling) -> {
                    exceptionHandling.accessDeniedHandler(myAccessDeniedHandler);
                })
                .build();
    }

    @Bean
    public CorsConfigurationSource configurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        source.registerCorsConfiguration("/**",corsConfiguration);

        return source;
    }
}
